class ContentScript {
  constructor() {
    this.floatingDiv = null
    this.searchResults = []
    this.currentKeyword = ''
    this.currentIndex = 0

    // 键盘事件
    this.keyboardEvents = null

    // Bind this to methods
    this.prevResult = this.prevResult.bind(this)
    this.nextResult = this.nextResult.bind(this)
    this.closeSearch = this.closeSearch.bind(this)
  }

  // eslint-disable-next-line class-methods-use-this
  isMac() {
    return navigator.platform.toUpperCase().indexOf('MAC') >= 0
  }

  /**
   * 创建浮动div
   */
  createFloatingDiv() {
    this.floatingDiv = document.createElement('div')
    this.floatingDiv.id = 'chm-search-floating'

    const previousKeyTips = this.isMac() ? '&#x2325;&#x2318;&#8593;' : 'Ctrl + Alt + &#8593;'
    const nextKeyTips = this.isMac() ? '&#x2325;&#x2318;&#8595;' : 'Ctrl + Alt + &#8595;'
    const escKeyTips = this.isMac() ? '&#x238B;' : 'Esc'

    this.floatingDiv.innerHTML = `
        <div id="chm-results-wrapper">
          <span class="keyword">Find: ${this.currentKeyword}</span>
          <span class="status">${this.currentIndex} / ${this.searchResults.length}</span>
        </div>
        <div id="chm-btn-wrapper">
          <button id="chm-btn-prev" data-tooltip="Previous(${previousKeyTips})">&#8593;</button>
          <button id="chm-btn-next" data-tooltip="Next(${nextKeyTips})">&#8595;</button>
          <button id="chm-btn-close" data-tooltip="Close(${escKeyTips})">Close</button>
        </div>
      `
    document.body.appendChild(this.floatingDiv)
    document.getElementById('chm-btn-prev').addEventListener('click', this.prevResult)
    document.getElementById('chm-btn-next').addEventListener('click', this.nextResult)
    document.getElementById('chm-btn-close').addEventListener('click', this.closeSearch)

    // 创建完 div 后添加键盘事件监听器
    this.bindKeyboardEvents(this)
  }

  /**
   * 上一个搜索结果
   */
  prevResult() {
    this.currentIndex = (this.currentIndex - 1 + this.searchResults.length) % this.searchResults.length
    this.scrollToCurrent()
  }

  /**
   * 下一个搜索结果
   */
  nextResult() {
    this.currentIndex = (this.currentIndex + 1) % this.searchResults.length
    this.scrollToCurrent()
  }

  scrollToCurrent() {
    document.querySelector('#chm-results-wrapper > .status').innerText = `${this.currentIndex + 1} / ${this.searchResults.length}`

    // 移除当前高亮元素的 'chm-current-highlight' 类
    if (this.searchResults.length > 0) {
      this.searchResults.forEach(node => node.classList.remove('chm-current-highlight'))
    }

    // 添加 'chm-current-highlight' 类到新的高亮元素
    this.searchResults[this.currentIndex].classList.add('chm-current-highlight')

    // 滚动到新的高亮元素
    this.searchResults[this.currentIndex].scrollIntoView({
      behavior: 'smooth',
      block: 'center',
      inline: 'nearest',
    })
  }

  /**
   * 关闭搜索
   */
  closeSearch() {
    // 移除高亮元素
    this.searchResults.forEach(node => {
      node.classList.remove('chm-current-highlight')
      node.classList.remove('chm-keyword-highlight')
    })

    // // 移除键盘事件监听器
    this.unbindKeyboardEvents()

    document.body.removeChild(this.floatingDiv)
    this.searchResults.length = 0
    this.floatingDiv = null
  }

  search(keyword) {
    this.currentKeyword = (keyword || '').trim()
    const elements = document.querySelectorAll('main div.group > div > div:nth-child(2) > div:first-child > div')
    elements.forEach(element => {
      this.highlight(element, this.currentKeyword)
    })

    if (this.searchResults.length > 0) {
      this.createFloatingDiv()
      this.currentIndex = this.searchResults.length - 1
      setTimeout(() => {
        this.scrollToCurrent()
      }, 200)
    }
  }

  highlight(node, keyword) {
    if (node.nodeType === Node.TEXT_NODE) {
      // // Check if the node has already been highlighted
      // if (node.className && node.className.includes('chm-keyword-highlight')) {
      //   return
      // }

      const regex = new RegExp(`(${keyword})`, 'gi')
      const parts = node.textContent.split(regex)

      if (parts.length > 1) { // 关键词在文本中存在
        const frag = document.createDocumentFragment()

        parts.forEach(part => {
          if (part.toLowerCase() === keyword.toLowerCase()) { // 这是关键词
            const span = document.createElement('span')
            span.className = 'chm-keyword-highlight'
            span.textContent = part
            frag.appendChild(span)
            this.searchResults.push(span)
          } else {
            frag.appendChild(document.createTextNode(part))
          }
        })

        node.parentNode.replaceChild(frag, node)
      }
    } else {
      node.childNodes.forEach(childNode => {
        if (childNode.nodeType === Node.ELEMENT_NODE
          && childNode.tagName.toLowerCase() === 'span'
          && childNode.className.includes('chm-keyword-highlight')) {
          // Skip this child node
          return
        }
        this.highlight(childNode, keyword)
      })
    }
  }

  /**
   * 绑定键盘事件
   */
  bindKeyboardEvents() {
    this.keyboardEvents = event => {
      if ((event.metaKey || event.ctrlKey) && event.altKey && event.keyCode === 40) {
        // Command + Option + Down
        // Ctrl + Alt + Down
        event.preventDefault()
        this.nextResult()
      } else if ((event.metaKey || event.ctrlKey) && event.altKey && event.keyCode === 38) {
        // Command + Option + Up
        // Ctrl + Alt + Up
        event.preventDefault()
        this.prevResult()
      } else if (event.keyCode === 27) {
        // Escape
        event.preventDefault()
        this.closeSearch()
      }
    }
    window.addEventListener('keydown', this.keyboardEvents)
  }

  /**
   * 移除键盘事件
   */
  unbindKeyboardEvents() {
    window.removeEventListener('keydown', this.keyboardEvents)
  }

  init() {
    // 从chrome.storage中searchFloating的配置
    chrome.storage.local.get('searchFloating', data => {
      if (!data.searchFloating) {
        return
      }

      // 判断url后面是否与searchFloating的conversationId相同
      const url = window.location.href
      const { conversationId, filter } = data.searchFloating

      if (!url.endsWith(conversationId)) {
        return
      }

      // 清空searchFloating的配置
      chrome.storage.local.set({ searchFloating: null })

      this.search(filter.search)
    })
  }
}

// 创建一个观察器实例
const observerMain = new MutationObserver(() => {
  // 检查特定的子节点是否存在
  if (document.querySelector('main') !== null) {
    observerMain.disconnect()

    // 如果存在，停止观察并高亮关键词
    // 创建一个观察器实例
    const observerGroup = new MutationObserver(async () => {
      observerGroup.disconnect()

      // 最多重试3次，每次时间多一倍，如果三次还没有，就放弃
      // 如果有就调用初始化，并且停止重试
      for (let i = 0; i < 3; i += 1) {
        await new Promise(resolve => {
          setTimeout(() => {
            resolve()
          }, 500 * (i + 1))
        })

        const targetNodeExists = document.querySelector('main div.group > div > div:nth-child(2) > div:first-child > div') !== null
        if (targetNodeExists) {
          setTimeout(() => {
            new ContentScript().init()
          }, 200)
          break
        }
      }
    })
    observerGroup.observe(document.querySelector('main'), { childList: true, subtree: true })
  }
})
observerMain.observe(document.body, { childList: true, subtree: true })

// ~ 样式
// ==============================
const style = document.createElement('style')
style.textContent = `
#chm-search-floating {
  position: fixed;
  top: 10px;
  right: 10px;
  width: 320px;
  background-color: rgba(224, 242, 241, 0.2);
  backdrop-filter: blur(3px);
  color: #fff;
  z-index: 1000;
  padding: 10px;
  border-radius: 5px;
}
#chm-results-wrapper {
  display: flex;
  justify-content: space-between;
}
#chm-results-wrapper span {
  padding: 8px;
  line-height: 20px;
  letter-spacing: 0.4px;
  font-size: 12px;
  font-weight: 400;
}
#chm-results-wrapper .keyword {
  width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#chm-results-wrapper .status {
  flex-shrink: 0;
  overflow: hidden;
  white-space: nowrap;
}
#chm-btn-wrapper {
  display: flex;
  justify-content: end;
}
#chm-btn-wrapper button {
  height: 28px;
  background: rgba(66,66,66, 0.3);
  font-size: 16px;
  border-radius: 4px;
  padding: 0 12px;
  font-weight: 500;
  letter-spacing: 0.15px;
  margin-left: 8px;
}
#chm-btn-wrapper button:hover {
  background-color: rgba(66, 66, 66, 0.5);
}
#chm-btn-wrapper button::before {
  content: attr(data-tooltip); /* 使用 data-tooltip 的值作为提示文字 */
  position: absolute;
  bottom: -24px; /* 调整提示文字的位置 */
  right: 0;
  background-color: rgba(66, 66, 66, 0.5);
  color: #fff;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  opacity: 0; /* 初始状态隐藏 */
  transition: opacity 0.3s ease;
}

#chm-btn-wrapper button:hover::before {
  opacity: 1; /* 鼠标悬停时显示提示文字 */
}
.chm-keyword-highlight {
  border-radius: 4px;
  background-color: #26A69A;
  color: #fff;
}
.chm-current-highlight {
  border-radius: 4px;
  background-color: #FF6F00;
}

`
document.head.appendChild(style)
